﻿/*
		12306 Auto Query => A javascript snippet to help you book tickets online.
		Copyright (C) 2011 Jingqin Lynn

		Includes jQuery
		Copyright 2011, John Resig
		Dual licensed under the MIT or GPL Version 2 licenses.
		http://jquery.org/license

		Includes Sizzle.js
		http://sizzlejs.com/
		Copyright 2011, The Dojo Foundation
		Released under the MIT, BSD, and GPL Licenses.

		This program is free software: you can redistribute it and/or modify
		it under the terms of the GNU General Public License as published by
		the Free Software Foundation, either version 3 of the License, or
		(at your option) any later version.

		This program is distributed in the hope that it will be useful,
		but WITHOUT ANY WARRANTY; without even the implied warranty of
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
		GNU General Public License for more details.

		You should have received a copy of the GNU General Public License
		along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

// ==UserScript==
// @name			12306 Auto Scripts
// @namespace		http://project.quietmusic.org/j/
// @description		A javascript to help you automaticly login, checking ticket and submit order.
// @match			http://dynamic.12306.cn/otsweb/*
// @match			https://dynamic.12306.cn/otsweb/*
// ==/UserScript==


/*************************************************
 * 12306 Server URL Configuration
 *************************************************/
var loginPath = "/otsweb/loginAction.do";
var queryActionPath = "/otsweb/order/querySingleAction.do";
var confirmOrderPath = "/otsweb/order/confirmPassengerAction.do";

/*************************************************
 * Configure JQuery Execute Environment
 *************************************************/
function withjQuery(callback, safe){
	if(typeof(jQuery) == "undefined") {
		var script = document.createElement("script");
		script.type = "text/javascript";
		script.src = "https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js";

		if(safe) {
			var cb = document.createElement("script");
			cb.type = "text/javascript";
			cb.textContent = "jQuery.noConflict();(" + callback.toString() + ")(jQuery);";
			script.addEventListener('load', function() {
				document.head.appendChild(cb);
			});
		}
		else {
			var dollar = undefined;
			if(typeof($) != "undefined") dollar = $;
			script.addEventListener('load', function() {
				jQuery.noConflict();
				$ = dollar;
				callback(jQuery);
			});
		}
		document.head.appendChild(script);
	} else {
		callback(jQuery);
	}
}


/*************************************************
 * Entry Point
 *************************************************/
(function (){
	var location = window.location;
	var path = location.pathname;

	console.error("Path: " + path);
	console.error("search: " + location.search);
	if ((path == loginPath && (location.search == "?method=init" || location.search == "?method=login")) || path == "/otsweb/login.jsp") {
		//登录页
		withjQuery(initLogin, true);
	} else if (path == queryActionPath) {
		withjQuery(initTicketQuery, true);
	} else if (path == confirmOrderPath) {
		withjQuery(initAutoCommitOrder, true);
	}
})();


/*************************************************
 * Automaticly Login
 *************************************************/
function initLogin() {

	var server = window.location.protocol + "//" + window.location.hostname;

	//var queryActionUrl = server + "/otsweb/order/querySingleAction.do?method=init";

	console.log("server = " + server);

	var notify = (function(){
		var notification = null;
		var _str, _timeout, _skipAlert;
		var showNotification = function() {
			closeNotification();
			if (_str && _str != "") {
				notification = webkitNotifications.createNotification(
					'http://www.12306.cn/mormhweb/images/favicon.ico',
					'订票',  // notification title
					_str
				);
				notification.show();
				if (_timeout) setTimeout(closeNotification, _timeout);
			}
		};

		var closeNotification = function() {
			if (notification) {
				notification.cancel();
				notification = null;
			}
		};

		var requestPermissionCb = function(){
			if (window.webkitNotifications.checkPermission() == 0) {
				showNotification();
			} else {
				if (!skipAlert) alert(str);
			}
		};

		return function (str, timeout, skipAlert) {
			_str = str;
			_timeout = timeout;
			_skipAlert = skipAlert;
			if (window.webkitNotifications) {
				if (window.webkitNotifications.checkPermission() != 0){
					window.webkitNotifications.requestPermission(requestPermissionCb);
				} else {
					showNotification();
				}
			} else {
				if (!skipAlert) alert(str);
			}
		};
	})();

	$("#UserName").val("SamCindy");
	$("#password").val("MyCindy1979");

	$("#loginForm").find("tr:last").after (
		'<tr>                                                                             \
			<td>&nbsp;</td>                                                               \
			<td>                                                                          \
				<a href="#" class="button_a" id="autoButton">                             \
					<span><ins id="autoButLabel">自动</ins></span>                        \
				</a>                                                                      \
			</td>                                                                         \
			<td>                                                                          \
				<div class="enter_rfont" id="submitLog">                                  \                                             \
				</div>                                                                    \
			</td>                                                                         \
		</tr>'
	);


	//For auto login operations: start, retry, stop
	var retryCount = 0;
	var isAutoLoginRunning = false;

	function start(func) {
		isAutoLoginRunning = true;
		retryCount = 0;

		$('#subLink').attr("disabled", true);
		$("#autoButLabel").css('color', 'red');
		$("#autoButLabel").text("停止");

		func();
	}

	function retry(func, timeout) {
		if (isAutoLoginRunning) {
			setTimeout(func, timeout);
		} else {
			$('#submitLog').text("");
			$("#autoButton").attr("disabled", false);
			$('#subLink').attr("disabled", false);
		}
	}

	function stop(errorText) {
		isAutoLoginRunning = false;
		retryCount = 0;

		$("#autoButLabel").css('color', 'white');
		$("#autoButLabel").text("自动");
		$("#autoButton").attr("disabled", true);

		if (errorText) {
			$("#submitLog").text(errorText).css('color', 'red');
		}
	}

	function tryToGetLoginRand() {
		retryCount++;
		$('#submitLog').text("第" + retryCount + "次尝试获得登陆码...").css('color', 'blue');

		$.ajax({
			url :server + '/otsweb/loginAction.do?method=loginAysnSuggest',
			type :"POST",
			dataType: "json",
			timeout: 30000,
			success: function(msg){
				if(msg.randError != 'Y'){
					console.error("tryToGetLoginRand reponse error:" + JSON.stringify(msg));
					retry(tryToGetLoginRand, 1000);
					return false;
				}
				else {
					//Got the login rand, submit login request.
					console.log("tryToGetLoginRand reponse success:" + JSON.stringify(msg));
					$("#loginRand").val(msg.loginRand);
					start(tryToLogin);
				}
			},
			error: function(XMLHttpRequest, textStatus, errorThrown) {
				console.error("tryToGetLoginRand request error: " + XMLHttpRequest.statusText + ", "  + textStatus + ", " + errorThrown);
				retry(tryToGetLoginRand, 1000);
				return false;
			}
		});
	}

	function tryToLogin() {
		retryCount++;
		$('#submitLog').text("(" + retryCount + ")次尝试登陆...").css('color', 'blue');

		if(('undefind' != $("[name='refundLoginCheck']"))&&($("[name='refundLoginCheck']").attr("checked")==true)){
			$("#refundLogin").val('Y');
		}else{
			$("#refundLogin").val('N');
		}

		$.ajax({
			url: server + $("#loginForm").attr("action"),
			type: $("#loginForm").attr("method"),
			data: {
				"loginRand": $("#loginRand").val(),
				"refundLogin": $("#refundLogin").val(),
				"refundFlag": $("#refundFlag").val(),
				"refundLoginCheck": $("#refundLoginCheck").val(),
				"loginUser.user_name": $("#UserName").val(),
				"user.password": $("#password").val(),
				"randCode": $("#randCode").val(),
				"nameErrorFocus": $("#nameErrorFocus").val(),
				"passwordErrorFocus": $("#passwordErrorFocus").val(),
				"randErrorFocus": $("#randErrorFocus").val(),
			},
			timeout: 30000,
			success: function (msg) {
				if (msg.indexOf('我的12306') > -1) {
					//window.location.href = queryActionUrl;
					var dnewDoc = document.open();
					dnewDoc.write(msg);
					dnewDoc.close();
					notify('登录成功，开始查询车票吧！', 5000, false);
				} else if (msg.indexOf('请输入正确的验证码') > -1) {
					stop("请输入正确的验证码");
				} else if (msg.indexOf('登录名不存在') > -1) {
					stop("登录名不存在");
				} else if (msg.indexOf('密码输入错误') > -1) {
					stop("密码输入错误");
				} else if (msg.indexOf('已经被锁定') > -1) {
					stop("已经被锁定");
				} else if (msg.indexOf('系统维护中') > -1) {
					stop("系统维护中");
				} else {
					console.error("tryToLogin failed, try again...");
					retry(tryToLogin, 1000);
				}
			},
			error: function(XMLHttpRequest, textStatus, errorThrown) {
				console.error("tryToLogin request error: " + XMLHttpRequest.statusText + ", "  + textStatus + ", " + errorThrown);
				retry(tryToLogin, 1000);
				return false;
			},
			beforeSend: function (XHR) {
				//alert("Data Saved: " + XHR);
			}
		});
	}


	$("#autoButton").click(function(event){
		if ($("#autoButLabel").text() == "自动") {
			start(tryToGetLoginRand);
		} else {
			stop();
		}
		event.preventDefault();
	});

}

/*************************************************
 * Automaticly Query Ticket
 *************************************************/
 function initTicketQuery(){
	var notify = (function(){
		var notification = null;
		var _str, _timeout, _skipAlert;
		var showNotification = function() {
			closeNotification();
			if (_str && _str != "") {
				notification = webkitNotifications.createNotification(
					'http://www.12306.cn/mormhweb/images/favicon.ico',
					'订票',  // notification title
					_str
				);
				notification.show();
				if (_timeout) setTimeout(closeNotification, _timeout);
			}
		};

		var closeNotification = function() {
			if (notification) {
				notification.cancel();
				notification = null;
			}
		};

		var requestPermissionCb = function(){
			if (window.webkitNotifications.checkPermission() == 0) {
				showNotification();
			} else {
				if (!skipAlert) alert(str);
			}
		};

		return function (str, timeout, skipAlert) {
			_str = str;
			_timeout = timeout;
			_skipAlert = skipAlert;
			if (window.webkitNotifications) {
				if (window.webkitNotifications.checkPermission() != 0){
					window.webkitNotifications.requestPermission(requestPermissionCb);
				} else {
					showNotification();
				}
			} else {
				if (!skipAlert) alert(str);
			}
		};
	})();

  	var form = $("form[name=querySingleForm] .cx_from");
 	form.find("tr:last").after(
		'<tr> \
			<td> \
				<label><input type="checkbox" checked=true id="autoReQuery"/>自动刷新</label> \
			</td> \
			<td> \
				<input id="stopReQuery" type="button" value="停止" style="display: none"/> \
			</td> \
		</tr> \
		<tr> \
			<td class="font_r">查询周期：</td> \
			<td> \
				<label> \
					<input type="text" value="6" size="4" id="refereshInterval" style="text-align:center;"/> \
					秒 \
				</label> \
			</td> \
			<td class="font_r">人数：</td> \
			<td> \
				<input type="text" value="2" size="4" id="peopleNum" style="text-align:center;"/> \
			</td> \
			<td class="font_r">座次选择：</td> \
			<td colspan="2"> \
				<label> \
					<input type="radio" name="seatsOption" value="all"/>所有座次 \
					<input type="radio" name="seatsOption" value="onlySleep" checked=true/>仅卧铺 \
					<input type="radio" name="seatsOption" value="onlySeat"/>仅座票 \
				</label> \
			</td> \
			<td colspan="2"> \
				<span id="requeryInfo"></span> \
				<span id="requeryTimer"></span> \
			</td> \
			</td> \
		</tr>'
 	);

 	var validateDigitValue = function(defValue, minValue) {
 		var value = $(this).val();

 		console.error("validateDigitValue, value : default ：min - " + value + ":" + defValue + ":" + minValue);

 		if (value == "") {
 			$(this).val(defValue);
 		} else {
	 		value = parseInt(value);
	 		if (isNaN(value) || value < minValue) {
	 			$(this).val(defValue);
	 		}
 		}
 	};

 	$("#refereshInterval").blur(validateDigitValue.bind($("#refereshInterval"), 6, 6));
 	$("#peopleNum").blur(validateDigitValue.bind($("#peopleNum"), 2, 1));


	var monitorTicketType = new Array();

 	var markMonitoredTicketOnUI = function (c, enable) {
 		c.css('color', enable?"red":"#055A78");
 	};

	var markAllMonitoredTicketsOnUI = function() {
		$(".hdr tr:eq(2) td").each(function (i, e) {
			markMonitoredTicketOnUI($(this), monitorTicketType[i]);
		});
	};

 	var setMonitoredTicket = function(i, c, enable) {
 		monitorTicketType[i] = enable;
 		markMonitoredTicketOnUI(c, enable);
 	};

	var setAllMonitoredTickets = function(opstr) {
		if (opstr == "all") {
			$(".hdr tr:eq(2) td").each(function (i, e) {
				if (i < 4) return;
				setMonitoredTicket(i, $(this), true);
			});
		}
		else if (opstr == "onlySleep") {
			$(".hdr tr:eq(2) td").each(function (i, e) {
				if ($(this).text().indexOf("卧") != -1) {
					setMonitoredTicket(i, $(this), true);
				} else {
					setMonitoredTicket(i, $(this), false);
				}
			});
		} else if (opstr == "onlySeat") {
			$(".hdr tr:eq(2) td").each(function (i, e) {
				if ($(this).text().indexOf("座") != -1) {
					setMonitoredTicket(i, $(this), true);
				} else {
					setMonitoredTicket(i, $(this), false);
				}
			});
		} else {
			$(".hdr tr:eq(2) td").each(function (i, e) {
				if (i < 3) return;
				setMonitoredTicket(i, $(this), false);
			});
		}
	};

 	var enableAutoQuery = function(enable){
 		if (enable) {
			$("#refereshInterval").attr("disabled", false);
			$("input[name=seatsOption]").attr("disabled", false);
			$("#requeryInfo").html("已启用自动刷新，请点击查询");
			$("#requeryTimer").html("");
			$("input[name=seatsOption]").each (function (i, e) {
				if ($(this).attr("checked")) {
					setAllMonitoredTickets($(this).val());
				}
			});
			console.log("Bind startQuery1");
			$("#submitQuery, #stu_submitQuery").click(startQuery);
 		} else {
			$("#refereshInterval").attr("disabled", true);
			$("input[name=seatsOption]").attr("disabled", true);
			$("#requeryInfo").html("");
 			$("#requeryTimer").html("");
			setAllMonitoredTickets();
			console.log("Unbind startQuery1");
			$("#submitQuery, #stu_submitQuery").unbind('click', startQuery);
 		}
 	};



 	$("#autoReQuery").click(function(event){
 		enableAutoQuery($(this).attr("checked"));
 	});

 	$("#stopReQuery").click(function(event){
 		stopRequery();
 	});

 	$("input[name=seatsOption]").click(function(event) {
 		console.error($(this).val());
 		setAllMonitoredTickets($(this).val());
 	});

	$(".hdr tr:eq(2) td").each(function (i, e) {
		$(this).click(function(event) {
			setMonitoredTicket(i, $(this), !monitorTicketType[i]);
		});
	});


	var submitButtonId = "";
	var timerCountDown = 0;
	var retryCount = 0;
	var isTicketAvilable = false;
	var autoRequery = false;
	var timer = null;

	var startQuery = function () {
		submitButtonId = $(this).attr("id");
		timerCountDown = 0
		retryCount = 1;
		isTicketAvilable = false;
		timer = null;

		autoRequery = $("#autoReQuery").attr("checked");

		console.log("submit");

		if (autoRequery) {
			$("#stopReQuery").show();
			$("#requeryInfo").html("已启用自动刷新：");
			$("#requeryTimer").html("正在第 " + retryCount + " 次查询..." );
		} else {
			$("#requeryInfo").text("");
			$("#requeryTimer").text("");
			$("#stopReQuery").hide();
		}
		notify("");
	};

	var doRequery = function() {
		retryCount++;
		$("#requeryTimer").html("正在第 " + retryCount + " 次查询..." );
		$("#"+submitButtonId).click();
 	};

  	var stopRequery = function() {
 		if (timer) {
 			clearTimeout(timer);
 			timer = null;
 		}
 		if (!isTicketAvilable) {
 			$("#requeryInfo").html("很遗憾，无指定的票，请稍候再试！");
 			notify("很遗憾，无指定的票!", 0, false);
 		}
 		$("#requeryTimer").html("");

 		autoRequery = false;
 		$("#stopReQuery").hide();
 		/*Bind startQuery on click event again to preparing next auto query as all click handers
 		  will have been unbinded when user click the buttons.*/
 		console.error("Bind startQuery2");
 		$("#submitQuery, #stu_submitQuery").click(startQuery);
 	};

 	var countDownTimer = function(){
		$("#requeryTimer").html(timerCountDown + " 秒后自动查询...");
		if (timerCountDown-- > 0) {
			timer = setTimeout(countDownTimer, 1000);
		} else {
			doRequery();
			timer = null;
		}
	};

	//Monitor the target grid
	var grid = $(".obj")[0];
	grid.addEventListener("DOMNodeInserted", function () {
		var row = $(event.target);
		var hasTicket = false;

		//if (isTicketAvilable) return;

		$("td", row).each(function (i, e) {
			if (i > 1 && monitorTicketType[i-1]){
				var el = $(e);
				var ticketNum = e.innerText.trim();
				if (ticketNum != "--" && ticketNum != "无") {
					console.error("ticketNum = " + ticketNum);
					if (ticketNum == "有") {
						hasTicket = true;
						el.css('background-color', 'lightblue ');
					} else {
						var ticketNum = parseInt(ticketNum);
						if (!isNaN(ticketNum) && ticketNum >= $("#peopleNum").val()) {
							hasTicket = true;
							el.css('color', 'red');
							el.css('background-color', 'yellow');
						}
					}
				}
			}
		});

		if (hasTicket) {
			isTicketAvilable = true;
			stopRequery();
			$("#requeryInfo").html("有票啦，快抢！！！");
			notify("有票啦，快抢！！！", 0, false);
			return;
		}

		if (!timer && !isTicketAvilable && autoRequery) {
			//If no timer, no ticket then create timer to prepare next query.
			console.error("Preparing requery");
			timerCountDown = Math.max(6, parseInt($("#refereshInterval").val()));
			countDownTimer();
		}
	}, true);

	/*For intialising*/
	enableAutoQuery($("#autoReQuery").attr("checked"));
 }

function initAutoCommitOrder() {
	var notify = (function(){
		var notification = null;
		var _str, _timeout, _skipAlert;
		var showNotification = function() {
			closeNotification();
			if (_str && _str != "") {
				notification = webkitNotifications.createNotification(
					'http://www.12306.cn/mormhweb/images/favicon.ico',
					'订票',  // notification title
					_str
				);
				notification.show();
				console.error("_timeout = " + _timeout);
				if (_timeout) setTimeout(closeNotification, _timeout);
			}
		};

		var closeNotification = function() {
			if (notification) {
				notification.cancel();
				notification = null;
			}
		};

		var requestPermissionCb = function(){
			if (window.webkitNotifications.checkPermission() == 0) {
				showNotification();
			} else {
				if (!skipAlert) alert(str);
			}
		};

		return function (str, timeout, skipAlert) {
			_str = str;
			_timeout = timeout;
			_skipAlert = skipAlert;
			if (window.webkitNotifications) {
				if (window.webkitNotifications.checkPermission() != 0){
					window.webkitNotifications.requestPermission(requestPermissionCb);
				} else {
					showNotification();
				}
			} else {
				if (!skipAlert) alert(str);
			}
		};
	})();

	var retryCount = 0;

	function stop(msg) {
		$("#tipresult").html("错误 - " + msg);
		$("div.tj_btn button, div.tj_btn input").each(function () { this.disabled = false; $(this).removeClass().addClass("long_button_u"); });
	}

	function submitForm() {
		if (!window.submit_form_check || !submit_form_check("confirmPassenger")) { notify("信息没有填写完整，或当前表单出现异常！", 3000, false); return; }

		retryCount++;
		$("#tipinfo").html("第 " + retryCount + " 次提交");

		jQuery.ajax({
			url: $("#confirmPassenger").attr('action'),
			data: $('#confirmPassenger').serialize(),
			type: "POST",
			timeout: 30000,
			success: function (msg) {
				var match = msg && msg.match(/org\.apache\.struts\.taglib\.html\.TOKEN['"]?\s*value=['"]?([^'">]+)/i);
				var newToken = match && match[1];
				if (newToken) {
					$("input[name='org.apache.struts.taglib.html.TOKEN']").val(newToken);
				}
				if (msg.indexOf('席位已成功锁定') > -1) {
					$("#tipresult").html("订票已成功！");
					notify("恭喜恭喜,车票预定成功,请尽快付款.", 0, false);
					window.location.replace("/otsweb/order/myOrderAction.do?method=queryMyOrderNotComplete&leftmenu=Y");
					return;
				}
				var reTryMessage = ['用户过多', '确认客票的状态后再尝试后续操作', '请不要重复提交'];
				for (var i = reTryMessage.length - 1; i >= 0; i--) {
					if (msg.indexOf(reTryMessage[i]) > -1) {
						$("#tipresult").html(reTryMessage[i]);
						submitForm();
						return;
					}
				};
				msg = msg.match(/var\s+message\s*=\s*"([^"]*)/);
				stop(msg && msg[1] || '出错了。。。。 啥错？ 我也不知道。。。。。');
			},
			error: function (msg) {
				$("#tipresult").html("当前请求发生错误");
				submitForm();
			}
		});
	}

	$('#rand').keyup(function(event) {
		if(event.which == 13) {
			$("#btnAutoSubmit").click();
		}
	});

	function setSeatDetailVEX(index) {
		return function () {
			$("#passenger_" + index + "_seat_detail").val(
				$("#passenger_" + index + "_seat_detail_select").val());
		}
	}

	for ( var i = 1; i <= 5; i++) {
		var checkValue = $("#passenger_" + i + "_seat").val();
		console.log("passenger_" + i + "_seat = " + checkValue);

		if (($("#passenger_" + i + "_seat_detail_select").length <= 0) && ($("#passenger_" + i + "_seat_detail").length <= 0)) {
			console.log("Enable seat detail select option by this extension!");
			$("#passenger_" + i + "_seat").after (
				'<select name="passenger_' + i + '_seat_detail_select" id="passenger_' + i + '_seat_detail_select" style="display: none;"> \
					<option value="0">随机</option> \
					<option value="1">上铺</option> \
					<option value="2">中铺</option> \
					<option value="3" selected="">下铺</option> \
				</select>\
				<input name="passenger_' + i + '_seat_detail" id="passenger_' + i + '_seat_detail" type="hidden" value="3"/>\
				'
			);

			$("#passenger_" + i + "_seat_detail_select").change(setSeatDetailVEX(i));

		} else {
			console.log("Seat detail select option are supported by 12306!");
		}

		$("#passenger_" + i + "_seat_detail_select")[0].style.display = "block";
	}

	$("div.tj_btn").before("<div style='text-align:center;'><span id='tipinfo'></span>：<span id='tipresult'></span></div>").append("<button class='long_button_u_down' type='button' id='btnAutoSubmit'>自动提交</button>");
	$("#btnAutoSubmit").click(function () { retryCount = 0; submitForm(); });
}